// 这是一个基于TCP传输协议的服务器与客户端间的通信应用实例
// 该函数表示TCP通信程序的服务器端，该服务器端使用25555作为通信端口
// 首先调用socket函数和bind函数建立套接字并绑定端口，然后调用listen函数等待客户端进行连接，
// 如果由客户端的连接信息，则使用accept函数接受该连接并创建一个子进程，在子进程中发送当前的时间信息，
// 最后在子进程退出的时候关闭该套接字接口。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>

#define SERV_PORT 25555		// 服务器接听端口号
#define BACKLOG 20		// 请求队列中允许请求数
#define BUF_SIZE 256		// 缓冲区大小

int main(int argc, char *argv[]){
	
	int ret;
	time_t tt;
	struct tm*ttm;
	char buf[BUF_SIZE];

	pid_t pid;	// 定义管道描述符
	int sockfd;	// 定义sock描述符
	int clientfd;	// 定义数据传输sock描述符

	struct sockaddr_in host_addr;		// 本机IP地址和端口信息
	struct sockaddr_in client_addr;		// 判断socket函数的返回值

	int length = sizeof client_addr;

	// 创建套接字
	sockfd = socket(AF_INET,SOCK_STREAM,0);	// TCP/IP协议，数据流套接字

	if(sockfd == -1){
		printf("套接字创建失败!\n");
		return 0;
	}

	// 绑定套接字
	bzero(&host_addr,sizeof(host_addr));	
	// TCP/IP协议
	host_addr.sin_family=AF_INET;		
	// 设定端口号
	host_addr.sin_port = htons(SERV_PORT);	
	// 本地IP地址
	host_addr.sin_addr.s_addr = INADDR_ANY; 

	ret = bind(sockfd, (struct sockaddr *)&host_addr, sizeof(host_addr));

	if(ret == -1){
		printf("调用bind失败!\n");
		return 1;
	}

	// 监听网络端口
	ret = listen(sockfd, BACKLOG);
	if(ret == -1){
		printf("调用listen函数失败!\n");
		return 1;
	}

	while(1){
		// 接收连接请求
		clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &length);
		if(clientfd == -1){
			printf("调用accept接收函数失败\n");
			return 1;
		}

		pid = fork();		// 创建子进程
		// 在子进程中处理
		if(pid == 0){
			while(1){
				bzero(buf,sizeof(buf));	// 首先清空缓冲区
				tt = time(NULL);
				ttm = localtime(&tt);	// 获取当前时间参数
				strcpy(buf,asctime(ttm));// 将时间信息copy进缓冲区
				send(clientfd,buf,strlen(buf),0);// 发送数据
				sleep(2);
			}

			close(clientfd);		// 调用close函数关闭连接
		}else if(pid >0)
		{	
			// 在父进程中关闭套接字，准备下一个客户端连接
			close(clientfd);
		}
	}

	return 0;
}

